package com.chenwc.serialassistant.threadpool.task;

import com.chenwc.serialassistant.util.Common;
import gnu.io.SerialPort;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.concurrent.Task;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

/**
 * 发送文件
 *
 * @author chenwc
 */
public class SendFileTask extends Task<Object> {

    private final static Logger logger = LoggerFactory.getLogger(SendFileTask.class);

    /**
     * 任务名称
     */
    private final String name;

    private final File file;
    private final SerialPort serialPort;
    private Integer sendLength;
    private final Label sendDataLength;
    private final TextArea displayTextArea;

    public SendFileTask(String name, File file, SerialPort serialPort, Integer sendLength, Label sendDataLength, TextArea displayTextArea) {
        this.name = name;
        this.file = file;
        this.serialPort = serialPort;
        this.sendLength = sendLength;
        this.sendDataLength = sendDataLength;
        this.displayTextArea = displayTextArea;
    }

    /**
     * 只读对象包装器
     */
    private ReadOnlyObjectWrapper<Integer> results =
            new ReadOnlyObjectWrapper<Integer>(this, "sendLength", this.sendLength);

    /**
     * 获取只读对象
     *
     * @return 只读对象
     */
    public final Integer getResults() {
        return results.get();
    }

    /**
     * 获取只读对象属性
     *
     * @return 对象属性
     */
    public final ReadOnlyObjectProperty<Integer> resultsProperty() {
        return results.getReadOnlyProperty();
    }

    @Override
    protected Object call() {

        if (file == null || !file.exists()) {
            Common.alert(Alert.AlertType.WARNING, "警告", "打开的文件为空或者不存在！");
            return null;
        }

        OutputStream os = null;
        try {
            byte[] bytes = FileUtils.readFileToByteArray(file);
            //获得串口的输出流
            os = serialPort.getOutputStream();
            Long t1 = System.currentTimeMillis();
            for (int j = 0; j < bytes.length; j++) {
                os.write(new byte[]{bytes[j]});
                //更新实际发送的数据长度
                sendLength = sendLength + 1;
                Platform.runLater(() -> {
                    //显示更新后的数据长度
                    sendDataLength.setText("Send: " + sendLength);
                });
                updateProgress(j, bytes.length);
            }
            Long t2 = System.currentTimeMillis();
            logger.info("发送文件耗时: {} ms", (t2 - t1));
            Platform.runLater(() -> displayTextArea.appendText("发送耗时：" + (t2 - t1) + " ms\n"));
        } catch (Exception e) {
            logger.error("Exception", e);
        } finally {
            try {
                if (os != null) {
                    os.flush();
                }
            } catch (IOException e) {
                logger.error("Exception", e);
            }
            IOUtils.closeQuietly(os);
        }
        results.set(sendLength);
        return sendLength;
    }

    @Override
    protected void succeeded() {
        super.succeeded();
        updateMessage("Done!");
        logger.info("{} is Done!", this);
    }

    @Override
    protected void cancelled() {
        super.cancelled();
        updateMessage("Cancelled!");
        logger.info("{} is Cancelled!", this);
    }

    @Override
    protected void failed() {
        super.failed();
        updateMessage("Failed!");
        logger.info("{} is Failed!", this);
    }

    @Override
    protected void running() {
        super.running();
        updateMessage("Running!");
        logger.info("{} is Running!", this);
    }

    @Override
    protected void scheduled() {
        super.scheduled();
        updateMessage("Scheduled!");
        logger.info("{} is Scheduled!", this);
    }

    /**
     * 获取任务名称
     *
     * @return 任务名称
     */
    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "SendFileTask [ name = " + name + " ]";
    }

}
